package com.dimples.dd.system.mapper;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dimples.dd.common.constant.DDConstant;
import com.dimples.dd.mybatis.core.mapper.BaseMapperX;
import com.dimples.dd.mybatis.core.query.LambdaQueryWrapperX;
import com.dimples.dd.mybatis.core.query.MPJLambdaWrapperX;
import com.dimples.dd.system.model.bo.RolePermsBO;
import com.dimples.dd.system.model.entity.SystemMenuDO;
import com.dimples.dd.system.model.entity.SystemRoleDO;
import com.dimples.dd.system.model.entity.SystemRoleMenuDO;
import com.dimples.dd.system.model.entity.SystemUserRoleDO;
import org.apache.ibatis.annotations.Mapper;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Mapper
public interface SystemRoleMenuMapper extends BaseMapperX<SystemRoleMenuDO> {

    /**
     * 获取权限和拥有权限的角色列表
     *
     * @param roleCode 角色编码
     * @return 角色菜单关联
     */
    default List<RolePermsBO> selectRolePermsList(String roleCode) {
        MPJLambdaWrapperX<SystemRoleMenuDO> wrapperX = new MPJLambdaWrapperX<>();
        wrapperX
                .selectAs(SystemRoleDO::getCode, RolePermsBO::getRoleCode)
                .selectCollection(SystemMenuDO.class, RolePermsBO::getPerms, map -> map
                        .result(SystemMenuDO::getPermission))
                .leftJoin(SystemMenuDO.class, SystemMenuDO::getId, SystemRoleMenuDO::getMenuId)
                .leftJoin(SystemRoleDO.class, SystemRoleDO::getId, SystemRoleMenuDO::getRoleId);
        if (StrUtil.isNotBlank(roleCode)) {
            wrapperX.eq(SystemRoleDO::getCode, roleCode);
        }
        wrapperX.isNotNull(SystemMenuDO::getPermission);
        return selectJoinList(RolePermsBO.class, wrapperX);
    }

    /**
     * 根据菜单ID删除角色菜单关联
     *
     * @param menuId 菜单ID
     */
    default void deleteListByMenuId(Long menuId) {
        delete(new LambdaQueryWrapper<SystemRoleMenuDO>().eq(SystemRoleMenuDO::getMenuId, menuId));
    }

    /**
     * 根据角色ID获取菜单ID集合
     *
     * @param roleId 角色ID
     * @return List<Long>
     */
    default List<Long> listMenuIdsByRoleId(Long roleId) {
        LambdaQueryWrapperX<SystemRoleMenuDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.select(SystemRoleMenuDO::getMenuId);
        wrapper.eqIfPresent(SystemRoleMenuDO::getRoleId, roleId);
        return selectList(wrapper).stream().map(SystemRoleMenuDO::getMenuId).collect(Collectors.toList());
    }

    /**
     * 获取角色的首页
     *
     * @param roleId 角色ID
     * @return 角色首页
     */
    default SystemRoleMenuDO selectRoleHomePageByRoleId(Long roleId) {
        LambdaQueryWrapperX<SystemRoleMenuDO> query = new LambdaQueryWrapperX<>();
        query.select(SystemRoleMenuDO::getRoleDefaultHome, SystemRoleMenuDO::getId);
        query.eqIfPresent(SystemRoleMenuDO::getRoleId, roleId)
                .isNotNull(SystemRoleMenuDO::getRoleDefaultHome).ne(SystemRoleMenuDO::getRoleDefaultHome, "");
        return this.selectOne(query);
    }

    /**
     * 根据用户ID获取首页
     *
     * @param userId 用户ID
     * @return 首页
     */
    default String selectHomePageByUserId(Long userId) {
        MPJLambdaWrapperX<SystemRoleMenuDO> wrapper = new MPJLambdaWrapperX<>();
        wrapper.select(SystemRoleMenuDO::getRoleDefaultHome)
                .leftJoin(SystemRoleDO.class, SystemRoleDO::getId, SystemRoleMenuDO::getRoleId)
                .leftJoin(SystemUserRoleDO.class, SystemUserRoleDO::getRoleId, SystemRoleDO::getId);
        wrapper.eqIfPresentOther(SystemUserRoleDO::getUserId, userId);
        wrapper.isNotNull(SystemUserRoleDO::getUserId).ne(SystemRoleMenuDO::getRoleDefaultHome, "");
        List<SystemRoleMenuDO> roleMenuDO = this.selectList(wrapper);
        // todo: 需考虑用户绑定多个角色的情况
        return CollUtil.isNotEmpty(roleMenuDO) && ObjectUtil.isNotEmpty(roleMenuDO.get(0)) ? roleMenuDO.get(0).getRoleDefaultHome() : DDConstant.HOME_PAGE_CODE;
    }

    /**
     * 根据角色ID集合查询角色菜单关联
     *
     * @param roleIds 角色ID集合
     * @return 角色关联菜单
     */
    default List<SystemRoleMenuDO> selectListByRoleId(Collection<Long> roleIds) {
        return selectList(SystemRoleMenuDO::getRoleId, roleIds);
    }

    /**
     * 根据角色ID查询角色菜单关联
     *
     * @param roleId 角色ID
     * @return 角色关联菜单
     */
    default List<SystemRoleMenuDO> selectListByRoleId(Long roleId) {
        return selectList(SystemRoleMenuDO::getRoleId, roleId);
    }

    /**
     * 根据角色ID和菜单ID集合删除角色菜单关联
     *
     * @param roleId        角色ID
     * @param deleteMenuIds 菜单ID集合
     */
    default void deleteListByRoleIdAndMenuIds(Long roleId, Collection<Long> deleteMenuIds) {
        delete(new LambdaQueryWrapper<SystemRoleMenuDO>()
                .eq(SystemRoleMenuDO::getRoleId, roleId)
                .in(SystemRoleMenuDO::getMenuId, deleteMenuIds));
    }
}